package com.whfc.fuum.manager.impl;

import com.whfc.common.enums.DeptType;
import com.whfc.common.exception.BizException;
import com.whfc.common.result.ResultEnum;
import com.whfc.fuum.dao.SysDeptExtMapper;
import com.whfc.fuum.dao.SysDeptMapper;
import com.whfc.fuum.dao.SysDeptUserMapper;
import com.whfc.fuum.dto.SysDeptDTO;
import com.whfc.fuum.entity.SysDept;
import com.whfc.fuum.entity.SysDeptExt;
import com.whfc.fuum.entity.SysDeptUser;
import com.whfc.fuum.manager.SysDeptManager;
import com.whfc.fuum.param.SysDeptAdd;
import com.whfc.fuum.param.SysDeptEdit;
import com.whfc.fuum.redis.SysDeptRedisDao;
import com.whfc.fuum.redis.SysUserRedisDao;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author qzexing
 * @version 1.0
 * @date 2021-03-11 14:59
 */
@Service
public class SysDeptManagerImpl implements SysDeptManager {


    @Autowired
    private SysDeptMapper sysDeptMapper;

    @Autowired
    private SysDeptRedisDao sysDeptRedisDao;

    @Autowired
    private SysUserRedisDao sysUserRedisDao;

    @Autowired
    private SysDeptUserMapper sysDeptUserMapper;

    @Autowired
    private SysDeptExtMapper sysDeptExtMapper;

    @Override
    public String getDeptNameById(Integer deptId) {
        SysDeptDTO deptDTO = this.getDeptDTOById(deptId);
        return deptDTO != null ? deptDTO.getName() : null;
    }

    @Override
    public SysDeptUser getDeptUserByUserId(Integer userId, Integer deptId) {
        return sysDeptUserMapper.selectDeptUserByUserId(userId, deptId);
    }

    @Override
    public SysDeptDTO getDeptDTOById(Integer deptId) {
        SysDeptDTO deptDTO = sysDeptRedisDao.getSysDept(deptId);
        if (deptDTO == null) {
            deptDTO = sysDeptMapper.selectById(deptId);
            sysDeptRedisDao.setSysDept(deptId, deptDTO);
        }
        return deptDTO;
    }

    @Override
    public SysDept addDept(SysDeptAdd deptAdd) {
        Integer type = deptAdd.getType();
        DeptType deptType = DeptType.parseValue(type);
        if (!DeptType.COMPANY.equals(deptType) && !DeptType.PROJECT.equals(deptType)) {
            throw new BizException(ResultEnum.PARAM_ERROR.getCode(), "组织机构目前只能添加公司或者项目!");
        }
        SysDept dept = new SysDept();
        Integer pid = deptAdd.getPid();
        if (pid == null) {
            //用户创建公司时，不传pid
            pid = 0;
            deptAdd.setPid(0);
        } else {
            SysDept sysDept = sysDeptMapper.selectByPrimaryKey(pid);
            if (DeptType.PROJECT.getValue().equals(sysDept.getType())) {
                throw new BizException(ResultEnum.PARAM_ERROR.getCode(), "项目类型下面不能添加公司或项目!");
            }
        }
        //检查是否重名
        String deptName = deptAdd.getName();
        SysDept sysDept = sysDeptMapper.selectByNameAndPid(deptName, pid);
        if (sysDept != null) {
            throw new BizException(ResultEnum.PARAM_ERROR.getCode(), "同级组织机构中已存在该名称");
        }

        String pids = "0";
        if (pid != 0) {
            pids = sysDeptMapper.selectDeptPath(pid);
        }
        BeanUtils.copyProperties(deptAdd, dept);
        dept.setPids(pids);
        //查询父节点的所有子节点个数
        List<SysDept> deptList = sysDeptMapper.selectChildDeptList(pid);
        //设置当前排序
        dept.setIndex(deptList.size() + 1);
        //设置guid
        String guid = deptAdd.getGuid();
        if (StringUtils.isBlank(guid)) {
            guid = UUID.randomUUID().toString().replace("-", "");
        }
        dept.setGuid(guid);
        sysDeptMapper.insertSelective(dept);
        //初始化组织机构扩展信息
        SysDeptExt record = new SysDeptExt();
        record.setDeptId(dept.getId());
        sysDeptExtMapper.insertSelective(record);
        //清除用户组织机构缓存
        sysUserRedisDao.deleteUserDeptIds();
        return dept;
    }

    @Override
    public void editDept(SysDeptEdit deptEdit) {
        Integer deptId = deptEdit.getDeptId();
        SysDept sysDept = sysDeptMapper.selectByPrimaryKey(deptId);
        if (sysDept == null) {
            throw new BizException(ResultEnum.PARAM_ERROR.getCode(), "该组织机构不存在!");
        }
        String name = deptEdit.getName();
        //检查是否重名
        SysDept dept = sysDeptMapper.selectByNameAndPid(name, sysDept.getPid());
        if (dept != null && !dept.getId().equals(deptId)) {
            throw new BizException(ResultEnum.PARAM_ERROR.getCode(), "同级组织机构中已存在该名称");
        }

        sysDept.setName(name);
        sysDeptMapper.updateByPrimaryKeySelective(sysDept);
        //删除缓存
        sysDeptRedisDao.remove(deptId);
        sysDeptRedisDao.remove(sysDept.getGuid());
    }

    @Override
    public void delDept(Integer deptId) {
        SysDept dept = sysDeptMapper.selectByPrimaryKey(deptId);
        if (dept == null) {
            throw new BizException(ResultEnum.PARAM_ERROR.getCode(), "该组织机构不存在!");
        }
        List<SysDept> childDeptList = sysDeptMapper.selectChildDeptList(deptId);
        if (childDeptList != null && childDeptList.size() > 0) {
            throw new BizException(ResultEnum.PARAM_ERROR.getCode(), "有下级组织机构,不能删除!");
        }
        //查看该组织下有没有用户
        List<Integer> userIdList = sysDeptUserMapper.selectUserIdListByDeptId(deptId);
        if (!userIdList.isEmpty()) {
            throw new BizException(ResultEnum.PARAM_ERROR.getCode(), "该组织机构下有用户,不能删除!");
        }
        //删除扩展信息
        sysDeptExtMapper.logicDeleteByDeptId(deptId);
        //删除组织机构
        sysDeptMapper.logicDeleteById(deptId);
        //移动排序字段
        Integer index = dept.getIndex();
        List<SysDept> deptList = sysDeptMapper.selectDeptByPidAndMoreIndex(dept.getPid(), index);
        for (SysDept sysDept : deptList) {
            sysDeptMapper.updateIndex(sysDept.getId(), sysDept.getIndex() - 1);
        }
        //删除缓存
        sysDeptRedisDao.remove(deptId);
        sysDeptRedisDao.remove(dept.getGuid());
    }

    @Override
    public List<SysDeptDTO> buildDeptTree(List<SysDeptDTO> deptDTOList) {
        //已遍历的缓存
        Map<Integer, SysDeptDTO> deptCache = new HashMap<>(deptDTOList.size());

        //根节点列表
        List<SysDeptDTO> rootDeptList = new ArrayList<>(deptDTOList.size());

        //遍历组织机构
        for (SysDeptDTO deptDTO : deptDTOList) {
            Integer id = deptDTO.getId();
            Integer pid = deptDTO.getPid();
            boolean hasPid = deptCache.containsKey(pid);
            //非根节点,则查找其父节点
            if (id > 0 && hasPid) {
                SysDeptDTO pDept = deptCache.get(pid);
                if (pDept.getChildren() == null) {
                    pDept.setChildren(new ArrayList<>());
                }
                pDept.getChildren().add(deptDTO);
            }
            //根节点
            else {
                rootDeptList.add(deptDTO);
            }
            //已遍历过的数据缓存
            deptCache.put(deptDTO.getId(), deptDTO);
        }
        return rootDeptList;
    }


    @Override
    public List<SysDeptDTO> getDescendantDeptListById(Integer deptId, String keyword) {
        //查询所有子孙节点
        List<SysDept> deptList = sysDeptMapper.selectDescendantDeptList(deptId, keyword);
        List<SysDeptDTO> deptDTOList = new ArrayList<>(deptList.size());
        for (SysDept dept : deptList) {
            SysDeptDTO deptDTO = new SysDeptDTO();
            BeanUtils.copyProperties(dept, deptDTO);
            deptDTO.setId(dept.getId());
            deptDTOList.add(deptDTO);
        }
        return deptDTOList;
    }

    @Override
    public SysDeptDTO selectSysDeptById(Integer deptId) {
        return sysDeptMapper.selectById(deptId);
    }
}
